package com.jsg.sl651.handler.mqtt;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.stereotype.Component;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;


/**
 * MQTT工具类
 */
@Slf4j
@Component
public class MQTTConnect {

    private final String HOST; //mqtt服务器的地址和端口号
    private final String productId;
    private final String deviceId;
    private String username = "admin";
    private String password = "admin";
    private String topic = "/{productId}/{deviceId}/properties/report";
    private MqttClient mqttClient;

    /**
     * 测试订阅消息
     */
//    public static void main(String[] args) throws Exception {
//        MQTTConnect mqttConnect = new MQTTConnect();
//        mqttConnect.start("admin","admin",30,false,true,60);
//        //订阅消息
//        mqttConnect.sub();
//        String productId1 = "1982336219521851392";
//        String deviceId1 = "0041141427";
//        Map<String,Object> map = new HashMap<>();
//        map.put("deviceId",deviceId1);
//        map.put("messageId",65535);
//        Map<String,Object> properties = new HashMap<String,Object>();
//        properties.put("F0H", "2025-10-26 16:10:00");
//        properties.put("22H", 0.5);
//        properties.put("20H", 2.5);
//        properties.put("26H", 753.5);
//        properties.put("38H", 13.3);
//        map.put("properties",properties);
//        JSONObject jsonObject1 = new JSONObject(map);
//        String msg = jsonObject1.toString();
//
//        mqttConnect.pub("/" + productId1 + "/" + deviceId1 + "/properties/report", msg,0);
//        mqttConnect.close();
//    }

    // 将字节数组转换为十六进制字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    public MQTTConnect() {
        HOST = "tcp://192.168.31.155:1883";
        productId = "1982336219521851392";
        deviceId = "0041141427";
    }
    public MQTTConnect(String host, String productId, String deviceId) {
        this.HOST = host;
        this.productId = productId;
        this.deviceId = deviceId;
    }
    private void createUserNameAndPassword(String uName, String pWord) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        this.username = uName + "|" + System.currentTimeMillis();
        this.password = bytesToHex(md.digest((this.username + "|" + pWord).getBytes()));
        this.topic = "/" + productId + "/" + deviceId + "/properties/report";
//        System.out.println("userName: " + this.username);
//        System.out.println("password: " + this.password);
//        System.out.println("topic: " + this.topic);
    }

    public void onStart() throws Exception {
        MQTTConnect mqttConnect = new MQTTConnect();
        mqttConnect.start();
    }

    public void start() throws Exception {
        createUserNameAndPassword(username, password);
        // host为主机名，deviceId即连接MQTT的客户端ID，一般以唯一标识符表示，MemoryPersistence设置deviceId的保存形式，默认为以内存保存
        mqttClient = new MqttClient(HOST, deviceId , new MemoryPersistence());
        // MQTT的连接设置
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        // 设置超时时间 单位为秒
        options.setConnectionTimeout(30);///默认：30
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(false);//默认：true
        // 设置断开后重新连接(设置为true时将启用自动重新连接)
        options.setAutomaticReconnect(true);//默认：false
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
        options.setKeepAliveInterval(60);//默认：60
        // 设置回调
        mqttClient.setCallback(new Callback());
        mqttClient.connect(options);
    }

    /**
     * 自定义mqtt连接
     * @param uName
     * @param pWord
     * @param connectionTimeout
     * @param cleanSession
     * @param automaticReconnect
     * @param keepAliveInterval
     * @throws MqttException
     */
    public void start(String uName, String pWord, int connectionTimeout, boolean cleanSession,boolean automaticReconnect, int keepAliveInterval) throws Exception {
        createUserNameAndPassword(uName,pWord);
        // host为主机名，deviceId即连接MQTT的客户端ID，一般以唯一标识符表示，MemoryPersistence设置deviceId的保存形式，默认为以内存保存
        mqttClient = new MqttClient(HOST, deviceId, new MemoryPersistence());
        // MQTT的连接设置
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        // 设置超时时间 单位为秒
        options.setConnectionTimeout(connectionTimeout);///默认：30
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(cleanSession);//默认：true
        // 设置断开后重新连接(设置为true时将启用自动重新连接)
        options.setAutomaticReconnect(automaticReconnect);//默认：false
        // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
        options.setKeepAliveInterval(keepAliveInterval);//默认：60
        // 设置回调
        mqttClient.setCallback(new Callback());
        mqttClient.connect(options);
    }

    /**
     * 关闭MQTT连接
     */
    public void close() throws MqttException {
        mqttClient.disconnect();
        mqttClient.close();
    }

    /**
     * 向某个主题发布消息
     *
     * @param topic: 发布的主题
     * @param msg:   发布的消息
     * @param qos:   消息质量    Qos：0、1、2
     */
    public void pub(String topic, String msg, int qos) throws MqttException {
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(qos);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
        log.info("----------向主题 "+ topic+ "发送消息: "+msg +" ----------");
    }
    public void pub(String msg, int qos) throws MqttException{
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(qos);
        mqttMessage.setPayload(msg.getBytes());
        MqttTopic mqttTopic = mqttClient.getTopic(topic);
        MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
        token.waitForCompletion();
        log.info("----------向主题 "+ topic+ "发送消息: "+msg +" ----------");
    }

    /**
     * 订阅某一个主题，可携带Qos
     *
     * @param topic 所要订阅的主题
     * @param qos   消息质量：0、1、2
     */
    public void sub(String topic, int qos) throws MqttException {
        mqttClient.subscribe(topic, qos);
    }

    public void sub() throws MqttException {
        topic =  String.format(topic, productId, deviceId);
        mqttClient.subscribe(topic, 0);
    }
}
